/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package envioyreciboficheros;

import java.util.ArrayList;
import javax.swing.table.DefaultTableModel;
import InfoFicheros.InfoFicheros;
import java.io.File;
import javax.swing.ListSelectionModel;
import InfoFicheros.MetodosGenerales;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;

/**
 *
 * @author oscarsoto
 */
public class PruebaFormulario extends javax.swing.JFrame {

    //Variables de conexion
    private static Socket cliente;
    private static DataInputStream entradaPrimitiva;
    private static ObjectInputStream entrada;
    private static DataOutputStream salidaPrimitiva;
    private static ObjectOutputStream salida;
    //Variables de directorio y separadores del sistema
    private static String BARRA_ANDROID = "/";
    private static String pathAndroid = "/storage";
    private static String pathLocal = System.getProperty("user.home");
    //Definimos la clase que tiene los metodos para la gestion y envio de ficheros, directorios, etc
    private static MetodosGenerales metodosGenerales = new MetodosGenerales();

    //Clase para Renderizar el JTable y que no se pueda modificar
    static class noEditableTableModel extends DefaultTableModel {

        @Override
        public boolean isCellEditable(int rowIndex, int vColIndex) {
            return false;
        } //return false: Desabilitar edición de celdas.
    }

    public PruebaFormulario() {
        initComponents();

        limpiarTabla(tablaRemota, labelPathRemoto);
        File directorio = new File(pathLocal);

        ArrayList<InfoFicheros> listaFicheros = MetodosGenerales.listarDirectorio(directorio.listFiles());
        mostrarDatos(listaFicheros, tablaLocal, labelPathLocal, pathLocal);
    }

    //Metodo para alinear y activar la seleccion simple del JTable
    public void modificarTabla(JTable tabla) {
        tabla.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); //Activamos la seleccion simple de la tabla

        DefaultTableCellRenderer modelocentrar = new DefaultTableCellRenderer(); //Alineamos a la derecha los datos de la 2 columna
        modelocentrar.setHorizontalAlignment(SwingConstants.RIGHT);
        tabla.getColumnModel().getColumn(1).setCellRenderer(modelocentrar);
    }

    @SuppressWarnings("unchecked")
    //Metodo para cargar los datos del ArrayList en la tabla, y mostrar en el JTextField la direccion    
    public void mostrarDatos(ArrayList<InfoFicheros> listaFicheros, JTable tabla, JTextField label, String path) {
        label.setText(path);
        noEditableTableModel modelo = new noEditableTableModel();

        modelo.addColumn("Nombre");
        modelo.addColumn("Tamaño Archivo");
        modelo.addColumn("Tipo Archivo");
        modelo.addColumn("Ultima Modificación");

        Object datos[] = new Object[4];

        String escribir;
        Path raizSistema = Paths.get(path);

        if (!path.equalsIgnoreCase(raizSistema.getRoot().toString()) && !path.equalsIgnoreCase(BARRA_ANDROID)) {
            datos[0] = "..";
            modelo.addRow(datos);
        }

        for (InfoFicheros fichero : listaFicheros) {
            datos[0] = fichero.getNombre();
            datos[2] = fichero.getTipo();
            if (fichero.getTamanno() != null) {
                datos[1] = fichero.getTamanno();
            } else {
                datos[1] = "";
            }
            datos[3] = fichero.getUltimaFecha();
            modelo.addRow(datos);
        }

        tabla.setModel(modelo);
        modificarTabla(tabla); //Bloqueamos la seleccion multiple y alineamos a la derecha la 2 columna

    }

    //Metodo para mostrar un mensaje emergente
    public void mensajeEmergente(String tipo, String mensaje, String titulo) {
        if (tipo.equalsIgnoreCase("INFORMACION")) {
            JOptionPane.showMessageDialog(null, mensaje, titulo, JOptionPane.INFORMATION_MESSAGE);
        } else if (tipo.equalsIgnoreCase("ERROR")) {
            JOptionPane.showMessageDialog(null, mensaje, titulo, JOptionPane.ERROR_MESSAGE);
        }
    }

    //Metodo para conectarse con el servidor
    public void conectarConServidor(String ipRemota, int puertoRemoto) {
        if (ipRemota.equalsIgnoreCase("") && puertoRemoto == 0) {
            mensajeEmergente("ERROR", "Tiene que rellenar la ip y el puerto", "Error de Conexión");
        } else if (ipRemota.equalsIgnoreCase("")) {
            mensajeEmergente("ERROR", "Tiene que rellenar la ip", "Error de Conexión");
        } else if (puertoRemoto == 0) {
            mensajeEmergente("ERROR", "Tiene que rellenar el puerto", "Error de Conexión");
        } else {
            try {
                InetAddress ip = InetAddress.getByName(ipRemota);
                cliente = new Socket(ip, puertoRemoto);

                salida = new ObjectOutputStream(cliente.getOutputStream());
                salidaPrimitiva = new DataOutputStream(cliente.getOutputStream());
                entrada = new ObjectInputStream(cliente.getInputStream());
                entradaPrimitiva = new DataInputStream(cliente.getInputStream());

                String mensaje = "LIST:" + pathAndroid; //Mensaje Ordenes

                salidaPrimitiva.writeUTF(mensaje); //Enviamos las Ordenes

                ArrayList<InfoFicheros> listaFicheros = (ArrayList<InfoFicheros>) entrada.readObject();
                mostrarDatos(listaFicheros, tablaRemota, labelPathRemoto, pathAndroid);

                botonConexionDesconexion.setText("Desconectar");
            } catch (Exception ConnectException) {
                mensajeEmergente("INFORMACION", "Es imposible conectarse al equipo, comprueba que la ip y el puerto es el correcto, y vuelva a intentarlo.", "Imposible Conectarse");
            }
        }
    }

    //metodo para desconectarse del servidor
    public void desconectarseServidor() {
        try {
            cliente.close();
            botonConexionDesconexion.setText("Conectar");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //Limpiar JTable y JField
    public void limpiarTabla(JTable tabla, JTextField label) {
        label.setText("");

        noEditableTableModel modelo = new noEditableTableModel();

        modelo.addColumn("Nombre");
        modelo.addColumn("Tamaño Archivo");
        modelo.addColumn("Tipo Archivo");
        modelo.addColumn("Ultima Modificación");

        tabla.setModel(modelo);
        modificarTabla(tabla); //Bloqueamos la seleccion multiple y alineamos a la derecha la 2 columna
    }

    //Cargar directorio remoto
    public void cargarDirectorioAndroid(String directorio) {
        System.out.println("Cargando");
        String mensaje = "LIST:" + directorio; //Mensaje Ordenes

        try {

            salidaPrimitiva.writeUTF(mensaje); //Enviamos las Ordenes
            ArrayList<InfoFicheros> listaFicheros = (ArrayList<InfoFicheros>) entrada.readObject();

            mostrarDatos(listaFicheros, tablaRemota, labelPathRemoto, directorio);

        } catch (java.io.EOFException eo) {
            mensajeEmergente("ERROR", "Se ha perdido la conexión, vuelta a conectarse", "Conexión Perdida");
            limpiarTabla(tablaRemota, labelPathRemoto);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //Pasamos un archivo local hacia android
    public void enviarArchivoaAndroid(String fichero, String direccionRemota) {
        File archivo = new File(fichero);
        String mensaje = "PUT:" + direccionRemota;

        try {

            if (archivo.isFile()) {
                salidaPrimitiva.writeUTF(mensaje);
                metodosGenerales.enviarFichero(fichero, salidaPrimitiva);
            } else {
                metodosGenerales.enviarCarpeta(fichero, pathAndroid, salidaPrimitiva);
            }

            Thread.sleep(1500);
            cargarDirectorioAndroid(pathAndroid);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //Pasamos un archivo de android hacia local
    public void enviarArchivoaLocal() {
    }

    public static void enviarFichero(String nombreFichero, DataOutputStream salidaPrimitiva) throws Exception {
        //Definimos las variables
        byte[] buffer = new byte[2048];
        int in = 0;
        int mbPasados = 0;
        File fichero = new File(nombreFichero);

        FileInputStream leerFichero = new FileInputStream(fichero);
        salidaPrimitiva.writeInt((int) fichero.length()); //Enviamos el temaño del fichero

        while ((in = leerFichero.read(buffer)) != -1) { //Enviamos el fichero
            salidaPrimitiva.write(buffer, 0, in);
            mbPasados += in;

            System.out.println(mbPasados + " Bytes pasados de " + Long.toString(fichero.length()) + "Bytes"); //Mostramos los bytes que se estan pasando(Esto hay que utilizarlo para mostrar una barra en el entorno grafico).
        }

        leerFichero.close(); //Cerramos el fichero
    }
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        tablaLocal = new javax.swing.JTable();
        jScrollPane2 = new javax.swing.JScrollPane();
        tablaRemota = new javax.swing.JTable();
        botonConexionDesconexion = new javax.swing.JButton();
        labelPathLocal = new javax.swing.JTextField();
        labelMensajesSistema = new javax.swing.JLabel();
        txtIp = new javax.swing.JTextField();
        txtPuerto = new javax.swing.JTextField();
        labelPathRemoto = new javax.swing.JTextField();
        btnEnviarAndroid = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        tablaLocal.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {

            }
        ));
        tablaLocal.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                MouseClickTablaLocal(evt);
            }
        });
        jScrollPane1.setViewportView(tablaLocal);

        tablaRemota.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {},
                {},
                {},
                {}
            },
            new String [] {

            }
        ));
        tablaRemota.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                MouseClickTablaRemota(evt);
            }
        });
        jScrollPane2.setViewportView(tablaRemota);

        botonConexionDesconexion.setText("Conectar");
        botonConexionDesconexion.setToolTipText("");
        botonConexionDesconexion.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                botonConexionDesconexionActionPerformed(evt);
            }
        });

        labelPathLocal.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                labelPathLocalActionPerformed(evt);
            }
        });

        labelMensajesSistema.setText("jLabel1");
        labelMensajesSistema.setToolTipText("");

        labelPathRemoto.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                labelPathRemotoActionPerformed(evt);
            }
        });

        btnEnviarAndroid.setText(">");
        btnEnviarAndroid.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnEnviarAndroidActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(20, 20, 20)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(labelMensajesSistema, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                            .add(txtIp)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, labelPathLocal)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 322, Short.MAX_VALUE))
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, layout.createSequentialGroup()
                                .add(18, 18, 18)
                                .add(txtPuerto, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 54, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .add(18, 18, 18)
                                .add(botonConexionDesconexion)
                                .add(0, 369, Short.MAX_VALUE))
                            .add(layout.createSequentialGroup()
                                .add(47, 47, 47)
                                .add(btnEnviarAndroid)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                                    .add(jScrollPane2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 331, Short.MAX_VALUE)
                                    .add(labelPathRemoto))
                                .add(61, 61, 61)))))
                .add(18, 18, 18))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                .addContainerGap(55, Short.MAX_VALUE)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(txtIp, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(txtPuerto, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(botonConexionDesconexion))
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(45, 45, 45)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                            .add(labelPathLocal, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                            .add(labelPathRemoto, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                        .add(18, 18, 18)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(jScrollPane2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 372, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                            .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 372, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                    .add(layout.createSequentialGroup()
                        .add(121, 121, 121)
                        .add(btnEnviarAndroid)))
                .add(18, 18, 18)
                .add(labelMensajesSistema)
                .add(15, 15, 15))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void botonConexionDesconexionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_botonConexionDesconexionActionPerformed
        String ipRemota = txtIp.getText();
        int puerto = 0;

        if (!txtPuerto.getText().equalsIgnoreCase("")) {
            puerto = Integer.parseInt(txtPuerto.getText());
        }

        if (botonConexionDesconexion.getText().equalsIgnoreCase("Conectar")) {
            conectarConServidor(ipRemota, puerto);
        } else {
            desconectarseServidor();
        }

    }//GEN-LAST:event_botonConexionDesconexionActionPerformed

    private void MouseClickTablaLocal(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_MouseClickTablaLocal
        if (evt.getClickCount() == 2) {
            String dato = String.valueOf(tablaLocal.getValueAt(tablaLocal.getSelectedRow(), 0));
            File directorio;
            ArrayList<InfoFicheros> listaFicheros;

            if (dato.equalsIgnoreCase("..")) {
                directorio = new File(pathLocal);
                pathLocal = directorio.getParent();

                listaFicheros = MetodosGenerales.listarDirectorio(directorio.getParentFile().listFiles());
                mostrarDatos(listaFicheros, tablaLocal, labelPathLocal, pathLocal);
            } else {
                Path raizSistema = Paths.get(pathLocal);
                String carpeta = raizSistema.resolve(dato).toString();

                directorio = new File(carpeta);

                if (directorio.isDirectory()) {
                    pathLocal = carpeta;
                    listaFicheros = MetodosGenerales.listarDirectorio(directorio.listFiles());
                    mostrarDatos(listaFicheros, tablaLocal, labelPathLocal, pathLocal);
                }
            }
        }
    }//GEN-LAST:event_MouseClickTablaLocal

    private void labelPathLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_labelPathLocalActionPerformed
        File directorio = new File(labelPathLocal.getText());

        if (directorio.isDirectory()) {
            pathLocal = labelPathLocal.getText();
            ArrayList<InfoFicheros> listaFicheros = MetodosGenerales.listarDirectorio(directorio.listFiles());
            mostrarDatos(listaFicheros, tablaLocal, labelPathLocal, pathLocal);
            labelMensajesSistema.setText("Correcto");
        } else {
            labelPathLocal.setText(pathLocal);
            labelMensajesSistema.setText("El path introducido no es una carpeta");
        }
    }//GEN-LAST:event_labelPathLocalActionPerformed

    private void MouseClickTablaRemota(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_MouseClickTablaRemota
        if (evt.getClickCount() == 2) {
            String dato = String.valueOf(tablaRemota.getValueAt(tablaRemota.getSelectedRow(), 0));
            String tipo = String.valueOf(tablaRemota.getValueAt(tablaRemota.getSelectedRow(), 2));

            if (dato.equalsIgnoreCase("..")) {
                Path direc = Paths.get(pathAndroid);
                String directorioPadre = direc.getParent().toString();

                if (directorioPadre.contains("\\")) {
                    directorioPadre = directorioPadre.replace("\\", BARRA_ANDROID);
                }

                pathAndroid = directorioPadre;
                cargarDirectorioAndroid(directorioPadre);
            } else {
                String carpeta = pathAndroid + BARRA_ANDROID + dato;

                if (tipo.equalsIgnoreCase("Directorio")) {
                    pathAndroid = carpeta;
                    cargarDirectorioAndroid(carpeta);
                }
            }
        }
    }//GEN-LAST:event_MouseClickTablaRemota

    private void btnEnviarAndroidActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnEnviarAndroidActionPerformed

        if (tablaLocal.getSelectedRow() <= -1) {
            mensajeEmergente("INFORMACION", "Lo siento, tiene que seleccionar algun elemento para pasar.", "Seleccione un dato");
        } else {

            String dato = String.valueOf(tablaLocal.getValueAt(tablaLocal.getSelectedRow(), 0));

            if (cliente == null || cliente.isClosed()) {
                mensajeEmergente("INFORMACION", "Lo siento no se pueden pasar datos sin estar conectado a un servidor.", "Conectese a un servidor");
            } else {

                System.out.println("Envio");
                Path raizSistema = Paths.get(pathLocal);
                String fichero = raizSistema.resolve(dato).toString();
                String ficheroAndroid = pathAndroid + BARRA_ANDROID + dato;

                enviarArchivoaAndroid(fichero, ficheroAndroid);
            }

        }

    }//GEN-LAST:event_btnEnviarAndroidActionPerformed

    private void labelPathRemotoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_labelPathRemotoActionPerformed
        String directorio = labelPathRemoto.getText();
        String mensaje = "ISDIRECTORY:" + directorio;

        try {
            if (!directorio.equalsIgnoreCase("") && cliente != null && cliente.isConnected()) {
                salidaPrimitiva.writeUTF(mensaje);
                String respuesta = entradaPrimitiva.readUTF();
                if(respuesta.equalsIgnoreCase("YES")){
                    cargarDirectorioAndroid(directorio);
                } else {
                    labelPathRemoto.setText(pathAndroid);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }//GEN-LAST:event_labelPathRemotoActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(PruebaFormulario.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(PruebaFormulario.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(PruebaFormulario.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(PruebaFormulario.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new PruebaFormulario().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton botonConexionDesconexion;
    private javax.swing.JButton btnEnviarAndroid;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JLabel labelMensajesSistema;
    private javax.swing.JTextField labelPathLocal;
    private javax.swing.JTextField labelPathRemoto;
    private javax.swing.JTable tablaLocal;
    private javax.swing.JTable tablaRemota;
    private javax.swing.JTextField txtIp;
    private javax.swing.JTextField txtPuerto;
    // End of variables declaration//GEN-END:variables
}
